﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Configuration;

namespace CoolCode.Services
{
    public static class ServiceFactory
    {
        private static readonly Collection<IServiceProvider> _providers = new Collection<IServiceProvider>();
        private static readonly ServiceProviderComparer comparer = new ServiceProviderComparer();
        private static readonly Dictionary<string, IServiceProvider> _providerCache = new Dictionary<string, IServiceProvider>();

        private readonly static object deleteMutex = new object();
        private readonly static object insertMutex = new object();

        static ServiceFactory()
        {
        }

        /// <summary>
        /// 加载appSettings里面指定的服务提供者(匹配以Service结尾的设置) 
        /// </summary>
        /// <param name="binDirectory">bin目录</param>
        public static void Load(string binDirectory)
        {
            var keys = ConfigurationManager.AppSettings.AllKeys;
            foreach (var k in keys)
            {
                if (k.EndsWith("Service") && !string.IsNullOrEmpty(ConfigurationManager.AppSettings[k])
                    && ConfigurationManager.AppSettings[k].Contains(","))
                {
                    Add(new DefaultServiceProvider(binDirectory, k));
                }
            }
        }

        public static void Add(IServiceProvider serviceProvider)
        {
            foreach (var p in _providers)
            {
                if (comparer.Equals(p, serviceProvider))
                {
                    _providers.Remove(p);
                    break;
                }
            }
            _providers.Add(serviceProvider);
        }

        public static T Produce<T>() where T : class
        {
            T service = null;
            string key = typeof(T).FullName;
            //从缓存里找
            if (_providerCache.ContainsKey(key))
            {
                service = _providerCache[key].ProvideService<T>();
                if (service != null)
                {
                    return service;
                }
                else
                {
                    lock (deleteMutex)
                    {
                        if (_providerCache.ContainsKey(key))//double check
                        {
                            _providerCache.Remove(key);
                        }
                    }
                }
            }
            //从提供的组件里找
            foreach (var p in _providers)
            {
                service = p.ProvideService<T>();
                if (service != null)
                {
                    if (!_providerCache.ContainsKey(key))
                    {
                        lock (insertMutex)
                        {
                            if (!_providerCache.ContainsKey(key))//double check
                            {
                                _providerCache.Add(key, p);
                            }
                        }
                    }
                    return service;
                }
            }
            throw new NullReferenceException(string.Format("Cannot found the service {0} ", key));
        }
    }

    internal class ServiceProviderComparer : IEqualityComparer<IServiceProvider>
    {
        public bool Equals(IServiceProvider x, IServiceProvider y)
        { 
            return (x.Name.Equals(y.Name));
        }

        public int GetHashCode(IServiceProvider obj)
        {
            return obj.Name.GetHashCode();
        }

    }
}
